package com.settlement.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.settlement.system.common.constant.SystemConstants;
import com.settlement.system.common.enums.AccountingEnum;
import com.settlement.system.common.enums.BillStatusEnum;
import com.settlement.system.common.enums.OrderEnum;
import com.settlement.system.common.util.DateUtils;
import com.settlement.system.common.util.NumberUtils;
import com.settlement.system.handler.disruptor.KafkaConsumer;
import com.settlement.system.mapper.SysAuditNoLinkMapper;
import com.settlement.system.mapper.SysBillMapper;
import com.settlement.system.model.entity.*;
import com.settlement.system.model.query.BillPageQuery;
import com.settlement.system.model.vo.SysBillVO;
import com.settlement.system.service.*;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 标准账单 服务实现类
 * </p>
 *
 * @author huangrensen
 * @since 2023-08-05
 */
@Service
@RequiredArgsConstructor
public class SysBillServiceImpl extends ServiceImpl<SysBillMapper, SysBill> implements SysBillService {

    private final Logger logger = LoggerFactory.getLogger(SysBillServiceImpl.class);

    private final SysAccountingProjectService sysAccountingProjectService;

    private final SysSubjectsService sysSubjectsService;

    private final SysPlatformService sysPlatformService;

    private final SysCompanyService sysCompanyService;

    private final SysStoreService sysStoreService;

    private final SnowflakeIdWorker snowflakeIdWorker = SnowflakeIdWorker.getInstance();

    private final SysBillDateLinkService sysBillDateLinkService;

    private final RedisTemplate redisTemplate;

    private final SysAuditNoLinkMapper auditNoLinkMapper;


    @Override
    public Page<SysBillVO> getBillPage(BillPageQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        // 拼接月份列表
        List<String> monthList = new ArrayList<>();
        String endMonthStr = queryParams.getEndMonth().replaceAll("-", "");
        LocalDate endMonth = LocalDate.parse(endMonthStr + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
        LocalDate startTime = LocalDate.parse(queryParams.getStartMonth().replaceAll("-", "") + "01", DateTimeFormatter.ofPattern(
                "yyyyMMdd"));
        // 获取已经生成的表名
        Object object = redisTemplate.opsForValue().get(SystemConstants.BILL_KEY);
        List<String> tableNameList;
        if (object != null) {
            tableNameList = (List<String>) object;
        } else {
            tableNameList = this.baseMapper.getAllTable();
            // 添加缓存
            redisTemplate.opsForValue().set(SystemConstants.BILL_KEY, tableNameList, 1, TimeUnit.HOURS);
        }
        // 循环追加月份
        while (!startTime.isAfter(endMonth)) {
            monthList.add(startTime.format(DateTimeFormatter.ofPattern("yyyyMM")));
            startTime = startTime.plusMonths(1);
        }
        // 根据月份判断数据库表是否存在
        List<String> existTableList = new ArrayList<>();
        String tableName;
        for (String month : monthList) {
            tableName = "sys_bill_%s".formatted(month);
            if (tableNameList.contains(tableName)) {
                existTableList.add(tableName);
            }
        }
        queryParams.setTableNameList(existTableList);
        Page<SysBillVO> pageVo = new Page<>();
        if (existTableList.size() == 0) {
            return pageVo;
        }
        Page<SysBill> page = new Page<>(pageNum, pageSize);
        StopWatch sw = new StopWatch();
        sw.start();
        this.baseMapper.getPage(page, queryParams);
        sw.stop();
        logger.info("查询所有数据耗时：{}", sw.getTotalTimeMillis());
        if (page.getTotal() > 0) {
            // 再通过ID查数据
            BillPageQuery pageQuery = new BillPageQuery();
            pageQuery.setTableNameList(existTableList);
            pageQuery.setIdList(page.getRecords().stream().map(SysBill::getId).toList());
            sw = new StopWatch();
            sw.start();
            List<SysBill> pageByIdList = this.baseMapper.getPageByIdList(pageQuery);
            sw.stop();
            logger.info("根据ID查数据耗时：{}", sw.getTotalTimeMillis());
            page.setRecords(pageByIdList);
        }
        BeanUtil.copyProperties(page, pageVo, "records");
        List<SysBill> records = page.getRecords();
        List<SysBillVO> recordVos = new ArrayList<>();
        for (SysBill record : records) {
            SysBillVO vo = new SysBillVO();
            BeanUtil.copyProperties(record, vo, "accessory", "otherAccessory");
            if (StringUtils.hasText(record.getAccessory())) {
                vo.setAccessory(JSONObject.parseObject(record.getAccessory(), Map.class));
            }
            if (StringUtils.hasText(record.getOtherAccessory())) {
                vo.setOtherAccessory(JSONObject.parseObject(record.getOtherAccessory(), Map.class));
            }
            recordVos.add(vo);
        }
        List<String> codes = new ArrayList<>();
        for (SysBill record : records) {
            codes.add(record.getLastCode());
            codes.add(record.getOtherLastCode());
        }
        List<SysSubjects> sysSubjectsList;
        if (codes.size() == 0) {
            sysSubjectsList = new ArrayList<>();
        } else {
            sysSubjectsList = sysSubjectsService.list(new LambdaQueryWrapper<SysSubjects>().in(SysSubjects::getLastCode, codes));
        }
        List<SysPlatform> platformList = sysPlatformService.list();
        List<SysCompany> sysCompanyList = sysCompanyService.list();
        for (SysBillVO recordVo : recordVos) {
            sysSubjectsList.stream().filter(sysSubjects -> sysSubjects.getLastCode().equals(recordVo.getLastCode()))
                    .findFirst()
                    .ifPresent(sysSubjects -> {
                        recordVo.setLastName(sysSubjects.getLastName());
                        recordVo.setFirstCode(sysSubjects.getFirstCode());
                        recordVo.setFirstName(sysSubjects.getFirstName());
                        recordVo.setBorrowing(sysSubjects.getBorrowing());
                    });
            sysSubjectsList.stream().filter(sysSubjects -> sysSubjects.getLastCode().equals(recordVo.getOtherLastCode()))
                    .findFirst()
                    .ifPresent(sysSubjects -> {
                        recordVo.setOtherLastName(sysSubjects.getLastName());
                        recordVo.setOtherFirstCode(sysSubjects.getFirstCode());
                        recordVo.setOtherFirstName(sysSubjects.getFirstName());
                        recordVo.setOtherBorrowing(sysSubjects.getBorrowing());
                    });
            // 对方账单金额
            recordVo.setOtherBillAmount(recordVo.getBillAmount());
            // 对账系统平台名称
            platformList.stream().filter(platform -> platform.getReconciliationSystemCode().equals(recordVo.getBillSystemPlatformCode()))
                    .findFirst()
                    .ifPresent(platform -> {
                        recordVo.setBillSystemPlatformName(platform.getReconciliationSystemName());
                    });
            // 入账主体
            sysCompanyList.stream().filter(sysCompany -> sysCompany.getCode().equals(recordVo.getCompanyCode()))
                    .findFirst()
                    .ifPresent(sysCompany -> recordVo.setCompanyCode(sysCompany.getName()));
            // 账单月份
            recordVo.setBillMonth(queryParams.getBillMonth());
        }
        pageVo.setRecords(recordVos);
        return pageVo;
    }

    @Override
    public Page<SysBill> getAllBillPage(BillPageQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        // 查询数据
        if (!StringUtils.hasText(queryParams.getTableName())) {
            String tableName = "sys_bill_%s".formatted(queryParams.getBillMonth());
            queryParams.setTableName(tableName);
        }
        if (!StringUtils.hasText(this.baseMapper.existTable(queryParams.getTableName()))) {
            return new Page<>(pageNum, pageSize);
        }
        Page<SysBill> page = new Page<>(pageNum, pageSize);
        return this.baseMapper.getAllPage(page, queryParams);
    }

    @Override
    public void updateBill(SysBill sysBill) {
        this.baseMapper.update(sysBill);
    }

    // 生成财务调账金额 或 自认损失金额 的标准账单

    /**
     * 需要注意的是，财务调账金额只会是覆盖
     * 自认损失金额会出现累加的情况，就是这个自认损失一部分，下次自认损失另一部分。这种情况就需要累加
     *
     * @param projectBill
     * @param platformKey
     * @param storeId
     * @param type        0 代表是财务调账 ， 1 代表是自认损失
     */
    @Override
    public void generateOtherBill(SysBill projectBill, String platformKey, Long storeId, int type) {
        BillPageQuery pageQuery = new BillPageQuery();
        pageQuery.setOriginalBillProject(projectBill.getOriginalBillProject());
        pageQuery.setLinkNo(projectBill.getLinkNo());
        pageQuery.setTableName(projectBill.getTableName());
        if (!StringUtils.hasText(this.baseMapper.existTable(projectBill.getTableName()))) {
            this.baseMapper.createTable(projectBill.getTableName());
        }
        List<SysBill> sysBillList = this.baseMapper.getList(pageQuery);
        SysPlatform sysPlatform = sysPlatformService.getByPlatformKey(platformKey);
        SysStore sysStore = sysStoreService.getById(storeId);
        // 填充平台和店铺基本信息
        this.fillBillProperties(projectBill, sysStore, sysPlatform);
        // 填充记账项目
        this.copyAccountingProject(projectBill, projectBill.getOriginalBillProject());
        SysBill bill = sysBillList.stream().filter(record -> record.equals(projectBill)).findFirst().orElse(null);
        if (Objects.isNull(bill)) {
            // 生成一条自认损失的标准账单
            projectBill.setId(snowflakeIdWorker.nextId(projectBill.getTableName().replaceAll("sys_bill_", "")));
            // 保存
            this.baseMapper.insertData(projectBill);
        } else {
            if (1 == type) {
                // 自认损失 累加
                bill.setBillAmount(projectBill.getBillAmount().add(bill.getBillAmount()));
            } else {
                // 只更新账单金额
                bill.setBillAmount(projectBill.getBillAmount());
            }
            // 更新
            this.baseMapper.update(bill);
        }
    }

    @Override
    public List<SysBill> getList(BillPageQuery queryParams) {
        if (!StringUtils.hasText(this.baseMapper.existTable(queryParams.getTableName()))) {
            return new ArrayList<>();
        }
        return this.baseMapper.getList(queryParams);
    }

    @Override
    public Set<String> columnList() {
        return SysBill.getColumnMap().keySet();
    }

    private void fillBillProperties(SysBill sysBill, SysStore sysStore, SysPlatform sysPlatform) {
        // 对账系统平台编码
        sysBill.setBillSystemPlatformCode(sysPlatform.getReconciliationSystemCode());
        // 对账系统店铺编码
        sysBill.setBillSystemStoreCode(sysStore.getBillSystemStoreCode());
        // 电商平台店铺编码
        sysBill.setCommercePlatformStoreCode(sysStore.getCommercePlatformStoreCode());
        // 电商平台店铺名称
        sysBill.setCommercePlatformStoreName(sysStore.getCommercePlatformStoreName());
        // 财务系统店铺编码
        sysBill.setBillSysStore(sysStore.getFinanceSystemStoreCode());
        // 财务系统店铺名称
        sysBill.setBillSysStoreName(sysStore.getFinanceSystemStoreName());
        // 电商平台店铺编码
        sysBill.setThirdSourceCode(sysStore.getCommercePlatformStoreCode());
        // 电商平台店铺名称
        sysBill.setThirdSourceName(sysStore.getCommercePlatformStoreName());
        // 统一账单ID
        sysBill.setSysBillId("ZD-%s-%s".formatted(sysStore.getBillSystemStoreCode(), DateUtils.getDateString()));
        // 入账主体
        sysBill.setCompanyCode(sysStore.getCompanyCode());
        // 记账状态
        sysBill.setStatus(BillStatusEnum.NO_FILE.getValue());
        // 会计期间 根据 出账日期 计算
        sysBill.setSysBillDate(DateUtils.formatDate(sysBill.getBillDate()));
        // 店铺属性
        sysBill.setStoreId(sysStore.getId());
    }

    private void copyAccountingProject(SysBill sysBill, String projectName) {
        // 取到平台补贴的记账项目配置
        SysAccountingProject project = sysAccountingProjectService.getListByAccountingProjectName(sysBill.getBillSystemPlatformCode(), projectName);
        if (project != null) {
            // 查询科目
            SysSubjects sysSubjects = sysSubjectsService.getByLastCode(project.getLastCode());
            if (sysSubjects != null) {
                // 记账状态
                if (AccountingEnum.YES.getValue().equals(project.getAccounting())) {
                    sysBill.setStatus(BillStatusEnum.NO.getValue());
                }
                // 记账项目
                sysBill.setBillProject(sysSubjects.getAccountingProject());
                // 末级科目编码
                sysBill.setLastCode(sysSubjects.getLastCode());
                // 生成记账项目
                sysBill.setBillProject("%s:%s_%s_%s".formatted(project.getBorrowing(), sysSubjects.getAccountingProject()
                        , sysSubjects.getLastCode(), sysSubjects.getLastName()));
            }
            sysSubjects = sysSubjectsService.getByLastCode(project.getOtherLastCode());
            if (sysSubjects != null) {
                // 末级科目编码
                sysBill.setOtherLastCode(sysSubjects.getLastCode());
            }
            // 辅助项配置
            sysBill.setAccessory(project.getAccessory());
            // 对方辅助项配置
            sysBill.setOtherAccessory(project.getOtherAccessory());
            // 是否分摊
            sysBill.setApportionment(project.getApportionment());
            // 票前票后
            sysBill.setInvoice(project.getInvoice());
            // 稽核标识
            sysBill.setAudit(project.getAudit());
            // 是否参与记账
            sysBill.setAccounting(project.getAccounting());
            // 供应商名称
            sysBill.setCarrier(project.getCarrier());
            // 借/贷
            sysBill.setBorrowing(project.getBorrowing());
            // 税额
            if (StringUtils.hasText(project.getRate())) {
                // 账单金额*税率；保留2位小数，四舍五入
                sysBill.setTaxAmount(sysBill.getBillAmount()
                        .multiply(NumberUtils.convertBigDecimal(project.getRate()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                        .setScale(2, RoundingMode.HALF_UP));
            }
        }
    }

    @Override
    public void checkAndSave(SysBill sysBill, SysStore sysStore, SysPlatform sysPlatform, String projectName, Map<String, KafkaConsumer.CommonItem> commonMap, String billType) {
        List<String> billDateList = this.getBillMonthListByLinkNo(sysBill.getLinkNo());
        List<SysBill> billList = new ArrayList<>();
        this.fillBillProperties(sysBill, sysStore, sysPlatform);
        this.copyAccountingProject(sysBill, projectName);
        String tableName;
        BillPageQuery pageQuery;
        List<SysBill> sysBills;
        if (StringUtils.hasText(sysBill.getLinkNo())) {
            // 避免查询全表
            for (String billMonth : billDateList) {
                tableName = "sys_bill_%s".formatted(billMonth);
                pageQuery = new BillPageQuery();
                pageQuery.setOriginalBillProject(sysBill.getOriginalBillProject());
                pageQuery.setLinkNo(sysBill.getLinkNo());
                pageQuery.setTableName(tableName);
                if (StringUtils.hasText(this.baseMapper.existTable(tableName))) {
                    sysBills = this.baseMapper.getList(pageQuery);
                    if (sysBills.size() > 0) {
                        billList.addAll(sysBills);
                    }
                }
            }
        }
        if (!StringUtils.hasText(this.baseMapper.existTable(sysBill.getTableName()))) {
            this.baseMapper.createTable(sysBill.getTableName());
            redisTemplate.delete(SystemConstants.BILL_KEY);
        }
        sysBill.setBillAmount(sysBill.getBillAmount().abs());
        boolean hasRecord = billList.stream().anyMatch(item -> item.isSameBill(sysBill));
        if (!hasRecord) {
            this.insertNewBill(sysBill);
        }
        // 取出相同的所有账单，判断月份是否在同一个月，不在需要删除，新增到对应月份
        List<SysBill> sameRecords = billList.stream().filter(item -> item.isSameBillProjectBill(sysBill)).toList();
        if (sameRecords.size() == 0) {
            return;
        }
        for (SysBill record : sameRecords) {
            // 需要再一次判断，如果record的业务日期和当前sysBill的业务日期不在一个月份，需要删除旧的账单，在新的业务日期对应的表插入一条账单
            if (!Objects.equals(record.getId().substring(0, 6), sysBill.getTableName().replaceAll("sys_bill_", ""))) {
                String newBillMonth = sysBill.getTableName().replaceAll("sys_bill_", "");
                this.baseMapper.deleteById("sys_bill_%s".formatted(record.getId().substring(0, 6)), record.getId());
                record.setTableName("sys_bill_%s".formatted(newBillMonth));
                record.setId(snowflakeIdWorker.nextId(newBillMonth));
                // 设置最新的业务日期
                record.setBusinessDate(sysBill.getBusinessDate());
                this.insertNewBill(record);
            } else {
                record.setTableName("sys_bill_%s".formatted(DateUtils.formatDate(record.getBusinessDate())));
                if (!StringUtils.hasText(record.getSettlementType())) {
                    record.setSettlementType(sysBill.getSettlementType());
                }
                this.baseMapper.update(record);
            }
        }
    }

    @Override
    public void saveCalculateBill(SysBill sysBill, SysStore sysStore, SysPlatform sysPlatform, String projectName) {
        this.fillBillProperties(sysBill, sysStore, sysPlatform);
        this.copyAccountingProject(sysBill, projectName);
        this.insertNewBill(sysBill);
    }

    @Override
    public List<SysBill> getListByLinkNoAndBillMonth(String linkNo, List<String> billDateList, List<String> calculateList) {
        String tableName;
        BillPageQuery queryParams;
        List<SysBill> allBillList = new ArrayList<>();
        if (!StringUtils.hasText(linkNo)) {
            return allBillList;
        }
        List<SysBill> list;
        for (String billMonth : billDateList) {
            tableName = "sys_bill_%s".formatted(billMonth);
            if (StringUtils.hasText(this.baseMapper.existTable(tableName))) {
                queryParams = new BillPageQuery();
                queryParams.setTableName(tableName);
                queryParams.setLinkNo(linkNo);
                queryParams.setOriginalBillProjectList(calculateList);
                list = this.baseMapper.getList(queryParams);
                if (list.size() > 0) {
                    for (SysBill sysBill : list) {
                        // 归档不处理
                        if (StringUtils.hasText(sysBill.getFileAuditId())) {
                            continue;
                        }
                        sysBill.setTableName(tableName);
                        allBillList.add(sysBill);
                    }
                }
            }
        }
        return allBillList;
    }

    @Override
    public void deleteOldRecords(List<SysBill> allBillList) {
        for (SysBill sysBill : allBillList) {
            this.baseMapper.deleteById(sysBill.getTableName(), sysBill.getId());
        }
    }

    @Override
    public void updateAuditId(SysBill sysBill, String auditId, String fileAuditId) {
        String tableName = sysBill.getTableName();
        if (StringUtils.hasText(this.baseMapper.existTable(tableName))) {
            this.baseMapper.updateAuditId(tableName, auditId, fileAuditId, sysBill.getId());
        }
    }

    @Override
    public List<String> getBillMonthListByLinkNo(String linkNo) {
        List<String> billMonthList = new ArrayList<>();
        if (!StringUtils.hasText(linkNo)) {
            return billMonthList;
        }
        int lastYear = 2024;
        List<Integer> yearList = new ArrayList<>();
        int year = LocalDate.now().getYear();
        while (year >= lastYear) {
            yearList.add(year);
            year--;
        }
        SysAuditNoLink query;
        List<SysAuditNoLink> list;
        for (Integer yearInt : yearList) {
            String tableName = "sys_audit_no_link_%s".formatted(yearInt);
            if (StringUtils.hasText(auditNoLinkMapper.existTable(tableName))) {
                query = new SysAuditNoLink();
                query.setTableName(tableName);
                query.setLinkNo(linkNo);
                query.setType(OrderEnum.BILL.getValue());
                list = auditNoLinkMapper.getList(query);
                if (list.size() > 0) {
                    for (SysAuditNoLink sysAuditNoLink : list) {
                        String[] strings = sysAuditNoLink.getTableId().split(",");
                        if (strings.length > 0) {
                            for (String bMonth : strings) {
                                if (!billMonthList.contains(bMonth)) {
                                    billMonthList.add(bMonth);
                                }
                            }
                        }
                    }
                }
            }
        }
        return billMonthList;
    }

    @Override
    public void updateBusinessDate(String linkNo, LocalDateTime businessDate) {
        if (!StringUtils.hasText(linkNo)) {
            logger.info("关联单号为空，updateBusinessDate方法无效...");
            return;
        }
        // 更新关联单号的月份
        // 先查找是否有记录
        int lastYear = 2024;
        List<Integer> yearList = new ArrayList<>();
        int year = LocalDate.now().getYear();
        while (year >= lastYear) {
            yearList.add(year);
            year--;
        }
        List<String> billMonthList = new ArrayList<>();
        String tableName;
        for (Integer yearInt : yearList) {
            tableName = "sys_audit_no_link_%s".formatted(yearInt);
            SysAuditNoLink query = new SysAuditNoLink();
            query.setTableName(tableName);
            query.setLinkNo(linkNo);
            query.setType(OrderEnum.BILL.getValue());
            if (!StringUtils.hasText(auditNoLinkMapper.existTable(tableName))) {
                auditNoLinkMapper.createTable(tableName);
            }
            List<SysAuditNoLink> auditNoLinkList = auditNoLinkMapper.getList(query);
            if (auditNoLinkList.size() > 0) {
                for (SysAuditNoLink sysAuditNoLink : auditNoLinkList) {
                    sysAuditNoLink.setTableName(tableName);
                    for (String bm : sysAuditNoLink.getTableId().split(",")) {
                        if (!billMonthList.contains(bm)) {
                            billMonthList.add(bm);
                        }
                    }
                }
            }
        }
        BillPageQuery queryParams;
        for (String billMonth : billMonthList) {
            tableName = "sys_bill_%s".formatted(billMonth);
            queryParams = new BillPageQuery();
            queryParams.setTableName(tableName);
            queryParams.setLinkNo(linkNo);
            if (!StringUtils.hasText(this.baseMapper.existTable(tableName))) {
                continue;
            }
            List<SysBill> sysBills = this.baseMapper.getList(queryParams);
            if (sysBills.size() > 0) {
                for (SysBill sysBill : sysBills) {
                    // 如果归档，则跳过
                    if (StringUtils.hasText(sysBill.getFileAuditId())) {
                        logger.info("归档账单不更新业务日期：" + sysBill);
                        continue;
                    }
                    sysBill.setBusinessDate(businessDate);
                    // 比较业务日期的月份是否与当前保存的表是否在同一张表，不在则需要移表
                    if (Objects.equals(DateUtils.formatDate(businessDate), sysBill.getId().substring(0, 6))) {
                        sysBill.setTableName(tableName);
                        this.baseMapper.update(sysBill);
                    } else {
                        // 先删除旧的记录
                        this.baseMapper.deleteById("sys_bill_%s".formatted(sysBill.getId().substring(0, 6)), sysBill.getId());
                        // 插入新的分表中
                        // 重新设置新表的ID
                        sysBill.setId(snowflakeIdWorker.nextId(DateUtils.formatDate(businessDate)));
                        sysBill.setTableName(tableName);
                        this.baseMapper.insertData(sysBill);
                    }
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void insertNewBill(SysBill sysBill) {
        // 生成ID
        sysBill.setId(snowflakeIdWorker.nextId(sysBill.getTableName().replaceAll("sys_bill_", "")));
        // 标准账单中的账单金额，都要进行绝对值转换成正数
        sysBill.setBillAmount(sysBill.getBillAmount().abs());
        if (!StringUtils.hasText(this.baseMapper.existTable(sysBill.getTableName()))) {
            this.baseMapper.createTable(sysBill.getTableName());
        }
        redisTemplate.delete(SystemConstants.BILL_KEY);
        // 保存
        this.baseMapper.insertData(sysBill);
        // 生成一个对应规则
        try {
            if (!StringUtils.hasText(sysBill.getLinkNo())) {
                return;
            }
            int year = LocalDate.now().getYear();
            String tableName = "sys_audit_no_link_%s".formatted(year);
            if (!StringUtils.hasText(auditNoLinkMapper.existTable(tableName))) {
                auditNoLinkMapper.createTable(tableName);
            }
            // 先查找是否有记录
            String tableBillMonth = sysBill.getTableName().replaceAll("sys_bill_", "");
            SysAuditNoLink query = new SysAuditNoLink();
            query.setTableName(tableName);
            query.setLinkNo(sysBill.getLinkNo());
            query.setType(OrderEnum.BILL.getValue());
            List<SysAuditNoLink> auditNoLinkList = auditNoLinkMapper.getList(query);
            if (auditNoLinkList.size() > 0) {
                SysAuditNoLink sysAuditNoLink = auditNoLinkList.get(0);
                if (!sysAuditNoLink.getTableId().contains(tableBillMonth)) {
                    sysAuditNoLink.setTableId(sysAuditNoLink.getTableId() + "," + tableBillMonth);
                    sysAuditNoLink.setTableName(tableName);
                    auditNoLinkMapper.update(sysAuditNoLink);
                }
            } else {
                SysAuditNoLink sysAuditNoLink = new SysAuditNoLink();
                sysAuditNoLink.setLinkNo(sysBill.getLinkNo());
                sysAuditNoLink.setType(OrderEnum.BILL.getValue());
                // 因为账单有多条，所以这里只要存账单的月份即可，到时查询根账单查关联单号
                sysAuditNoLink.setTableId(tableBillMonth);
                sysAuditNoLink.setTableName(tableName);
                auditNoLinkMapper.insertData(sysAuditNoLink);
            }
        } catch (Exception e) {
            logger.error("保存一份核销单对应关系失败，标准账单详情：" + sysBill);
        }
        // 新增一条平台的记账日期月份对应标准账单表名的对应关系
        try {
            if (Objects.nonNull(sysBill.getBillDate())) {
                SysBillDateLink sysBillDateLink = new SysBillDateLink();
                sysBillDateLink.setBillDateMonth(DateUtils.formatDate(sysBill.getBillDate()));
                sysBillDateLink.setStoreId(sysBill.getStoreId());
                sysBillDateLink.setTableName(sysBill.getTableName());
                sysBillDateLinkService.save(sysBillDateLink);
            }
        } catch (Exception ignore) {
            // logger.error("新增一条平台的记账日期月份对应标准账单表名的对应关系: " + e.getMessage());
        }
    }
}
